package {
	import flash.filesystem.File;
	import flash.filesystem.FileMode;
	import flash.filesystem.FileStream;	
	
	/**
	 * Parse config.xml.
	 * 
	 * Retrieve all channel URLs.
	 */
	public class ConfigManager {		
		/**
		 * Return read data.
		 * 
		 * @return xml that represents the data.
		 * 			<config>
		 *             <channelURL url="http://foo.com" lastItemTime="UNIX TIME IN MILLISECONDS"/>
		 * 			</config>
		 * 
		 * @param config reference to config.xml.
		 */
		public function loadConfigData(config:File):XML {
			configFile = config;
			
			// Open file for reading. If file doesn't exist, then create one.
			var configStream:FileStream = new FileStream();
			configStream.open(config, FileMode.UPDATE);
			
			// If config.xml has no data, then create data.
			// If no data exists, then an element is added, however, it will ony
			// be written if a channel is added successfully. 
			if (configStream.bytesAvailable == 0) {
				configData = <config></config>;
			} else {
				configData = XML(configStream.readUTFBytes(configStream.bytesAvailable));
			}

			configStream.close();
			
			return configData;
		}
		
		/**
		 * Removes a channel from the list.
		 */
		public function removeChannel(channelURL:String):Boolean {
			var config:XML = <config></config>;
			
			// Attach each channel to a new XML item, however, exclude the one
			// item with url equals to channel URL.	
			var elementFound:Boolean = false;
			for each (var channel:XML in configData.*) {
				if (channel.@url != channelURL) {
					config.appendChild(channel);
				} else {
					elementFound = true;
				}
			}
			
			// Element wasn't found, therefore not removed.
			if (!elementFound) {
				return false;
			}
			
			// Open config file for writing.
			var configStream:FileStream = new FileStream();
			configStream.open(configFile, FileMode.WRITE);	
			
			configStream.writeUTFBytes("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + 
										config.toXMLString());
			
			configStream.close();
			
			configData = config;
			
			return true;		
		}
		
		/**
		 * Add a channel to the config file.
		 * 
		 * @param channelURL channel URL
		 */
		public function addChannel(channelURL:String, name:String):Boolean {
			var newChannel:XML = new XML('<channel url="' + channelURL +  
										'" lastItemTime="0" name="'+ name +'"/>');
			
			// Check if the url is already stored.
			for each (var channel:XML in configData.*) {
				if (channel.@url == channelURL) {
					return false;
				}
			}
			
			configData.appendChild(newChannel);
			
			// Open config file for writing.
			var configStream:FileStream = new FileStream();
			configStream.open(configFile, FileMode.WRITE);	
			
			configStream.writeUTFBytes("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + 
										configData.toXMLString());
			
			configStream.close();			
			
			return true;
		}
		
		/**
		 * Return a list of channels.
		 * 
		 * @return Returns an Object with two instances, channelURL, name
		 *                 and lastItemTime.
		 */
		public function getChannels():Array {
			var channels:Array = new Array();
			
			for each (var channel:XML in configData.*) {
				var itemObj:Object = new Object();
				itemObj.channelURL = channel.@url;
				itemObj.lastItemTime = channel.@lastItemTime;
				itemObj.name = channel.@name;
				
				channels.push(itemObj);
			}
			
			return channels;
		}
		
		/**
		 * Write the last time each channel published an item.
		 * 
		 * @param Object a mapping between rss url and time in milliseconds.
		 */
		public function updateItemTimes(times:Object):void {			
			for each (var channel:XML in configData.*) {
				channel.@lastItemTime = times[channel.@url];
			}
			
			// Open config file for writing.
			var configStream:FileStream = new FileStream();
			configStream.open(configFile, FileMode.WRITE);	
			
			configStream.writeUTFBytes("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + 
										configData.toXMLString());
			
			configStream.close();				
		}
		
		private var configFile:File; // Reference to the config.xml file.
		private var configData:XML;  // Data of config.xml file. All the configuration
									 // changes are made to this object, then this object
									 // is written out as a file.
		
	}
}